package br.edu.unifei.cct720.trabalho04.utils.formas;

import java.awt.Color;

import br.edu.unifei.cct720.trabalho04.utils.BoundingBox;
import br.edu.unifei.cct720.trabalho04.utils.ponto.Ponto;
import br.edu.unifei.cct720.trabalho04.utils.ponto.Pontos;

public class Objeto implements FormaGeometrica {
	
	// Declaracao das variaveis de instancia
	private Ponto centroG = null;
	private int numero = 0;
	private int alturaInterno = 0;
	private int larguraInterno = 0;
	private int espessura = 0;
	private boolean dentroArea = false;
	private boolean estaNaBorda = false;

	/**
	 * Construtor 
	 * 
	 * @param Ponto centro
	 * @param int alturaInterno
	 * @param int larguraInterno
	 * @param int espessura
	 */
	public Objeto(Ponto centro, int alturaInterno, int larguraInterno, int espessura) {
		this.centroG = centro;
		this.alturaInterno = alturaInterno;
		this.larguraInterno = larguraInterno;
		this.espessura = espessura;
	}

	/**
	 * Metodo responsavel por retornar o conjunto de pontos
	 * do objeto
	 * 
	 * @return Pontos
	 */
	public Pontos getPontos() {
		Pontos pontos = new Pontos();
		// extremos do retangulo interno
		int extremoEsquerdo = centroG.getX() - (int)(this.larguraInterno/2) ;
		int extremoDireito 	= centroG.getX() + (int)(this.larguraInterno/2);
		int extremoSuperior	= centroG.getY() + (int)(this.alturaInterno/2);
		int extremoInferior	= centroG.getY() - (int)(this.alturaInterno/2);
		
		Reta retaSupInterno = new Reta (new Ponto(extremoEsquerdo, extremoSuperior), 
										new Ponto(extremoDireito, extremoSuperior));
		Reta retaDirInterno = new Reta (new Ponto(extremoDireito, extremoInferior), 
										new Ponto(extremoDireito, extremoSuperior));
		Reta retaEsqInterno = new Reta (new Ponto(extremoEsquerdo, extremoInferior), 
										new Ponto(extremoEsquerdo, extremoSuperior));
		Reta retaInfInterno = new Reta (new Ponto(extremoEsquerdo, extremoInferior), 
										new Ponto(extremoDireito, extremoInferior));
		Reta retaSupExterno = new Reta (new Ponto( extremoEsquerdo, extremoSuperior + espessura ), 
				 						new Ponto( extremoDireito, extremoSuperior + espessura ));
		Reta retaDirExterno = new Reta (new Ponto( extremoDireito + espessura, extremoInferior ), 
										new Ponto( extremoDireito + espessura, extremoSuperior ));
		Reta retaEsqExterno = new Reta (new Ponto( extremoEsquerdo - espessura, extremoInferior), 
				 						new Ponto( extremoEsquerdo - espessura, extremoSuperior ));
		Reta retaInfExterno = new Reta (new Ponto( extremoEsquerdo, extremoInferior - espessura), 
				 						new Ponto( extremoDireito, extremoInferior - espessura));
		
		Arco arco1 = new Arco(new Ponto(extremoDireito, extremoSuperior), espessura, 270, 360);
		Arco arco2 = new Arco(new Ponto(extremoDireito, extremoSuperior), espessura, 180, 270);
		Arco arco3 = new Arco(new Ponto(extremoDireito, extremoInferior), espessura, 90, 180);
		Arco arco4 = new Arco(new Ponto(extremoDireito, extremoInferior), espessura, 0, 90);
		
		pontos.addAll(retaSupExterno.getPontos());
		pontos.addAll(retaDirExterno.getPontos());
		pontos.addAll(retaEsqExterno.getPontos());
		pontos.addAll(retaInfExterno.getPontos());
		pontos.addAll(retaSupInterno.getPontos());
		pontos.addAll(retaDirInterno.getPontos());
		pontos.addAll(retaEsqInterno.getPontos());
		pontos.addAll(retaInfInterno.getPontos());
		pontos.addAll(arco1.getPontos());
		pontos.addAll(arco2.getPontos());
		pontos.addAll(arco3.getPontos());
		pontos.addAll(arco4.getPontos());
		
		return pontos;
	}

	/**
	 * Metodo responsavel por determinar se determinado ponto pertence ao objeto
	 * 
	 * @param Ponto ponto
	 * @return boolean
	 */
	public boolean pertence (Ponto ponto) {
		BoundingBox box = this.getBoundingBox();				
		// Testa se esta dentro da bounding box
		if (ponto.getX() >= box.getXMin() && ponto.getX() <= box.getXMax() && 
			 ponto.getY() >= box.getYMin() && ponto.getY() <= box.getYMax()) {
			// Se esta dentro da borda de dentro
			if ((ponto.getX() >= (box.getXMin()+espessura) && ponto.getX()<=(box.getXMax()-espessura)) ||
			     (ponto.getY() >= (box.getYMin()+espessura) && ponto.getY()<=(box.getYMax()-espessura))) {
				return true;				
			}
			
			ponto.setX(Math.abs( ponto.getX() - this.getCentroG().getX() ) - (int)(larguraInterno/2));
			ponto.setY(Math.abs( ponto.getY() - this.getCentroG().getY() ) - (int)(alturaInterno/2));
			
			if (Math.pow(ponto.getX(), 2.0)+Math.pow(ponto.getY(), 2.0) < espessura * espessura) return true;		
		}			
		return false;		
	}	
	
	/**
	 * Metodo responsavel por retornar o objeto 2D representativo deste objeto
	 * 
	 * @return BoundingBox
	 */
	public BoundingBox getBoundingBox() {
		int extremoEsquerdo = centroG.getX() - (int)(this.larguraInterno/2) - this.espessura;
		int extremoDireito 	= centroG.getX() + (int)(this.larguraInterno/2) + this.espessura;
		int extremoSuperior	= centroG.getY() + (int)(this.alturaInterno/2)  + this.espessura;
		int extremoInferior	= centroG.getY() - (int)(this.alturaInterno/2)  - this.espessura;		
		return new BoundingBox (extremoEsquerdo, extremoInferior, extremoDireito, extremoSuperior);		
	}
	
	// Metodos getters e setters
	public int getAlturaInterno() {
		return alturaInterno;
	}

	public void setAlturaInterno(int alturaInterno) {
		this.alturaInterno = alturaInterno;
	}

	public Ponto getCentroG() {
		return centroG;
	}

	public void setCentroG(Ponto centroG) {
		this.centroG = centroG;
	}

	public int getExpessura() {
		return espessura;
	}

	public void setExpessura(int espessura) {
		this.espessura = espessura;
	}

	public int getLarguraInterno() {
		return larguraInterno;
	}

	public void setLarguraInterno(int larguraInterno) {
		this.larguraInterno = larguraInterno;
	}

	public int getNumero() {
		return numero;
	}

	public void setNumero(int numero) {
		this.numero = numero;
	}

	public boolean isDentroArea() {
		return dentroArea;
	}

	public void setDentroArea(boolean dentroArea) {
		this.dentroArea = dentroArea;
	}

	public boolean isEstaNaBorda() {
		return estaNaBorda;
	}

	public void setEstaNaBorda(boolean estaNaBorda) {
		this.estaNaBorda = estaNaBorda;
	}
}
